package cn.itcast.pattern.singleton;

/**
 * 上面是双重检查的正确代码，这样写是为了解决以下问题：
 * 保证对象是单例的。
 * 保证synchronized只在第一次调用，节省开销。
 * 防止了重排序带来的隐患
 */
public class SingletonExample {
    private volatile static SingletonExample singletonExample;   //使用volite修饰禁止了重排序
    public SingletonExample getInstance(){
        if (singletonExample==null){
            synchronized (SingletonExample.class){   //保证这个锁只被加载一次，只是用一次
                if (singletonExample==null){
                    singletonExample=new SingletonExample();
                }
            }
        }
        return singletonExample;
    }
    /**
     * 考虑重排序的情况，
     * 对象初始化步骤为：
     * 1.分配内存空间
     * 2.将对象指向刚分配的内存空间
     * 3.初始化对象
     * 这时候会发生这种情况，比如说 线程t1 检查到SingletomExample为空，然后获取锁，然后再次检查到SingletomExample为空，为SingletomExample分配内存空间，但是还没有初始化完成这个对象
     * 然后t2线程会判断SingletomExample这个对象不为空(此时虽然地址不为空，但却未初始化)访问SingletomExample（此时对象还未完成初始化），
     * 之后t1会初始化这个对象
     */


}
